package p.ithorns.tools.translator.apt.model;

import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import p.ithorns.tools.translator.apt.utils.AptUtil;

import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

/**
 * FieldMeta
 * <p>
 * 字段元数据
 *
 * @author HtL
 * @date 2024/6/5 18:49
 * @since 1.0.0
 */
public class FieldMeta {

    /**
     * 字段名
     */
    private String name;

    /**
     * 指定Label
     * 如未指定，默认为name+Label 如xxxLabel
     */
    private String label;

    private String metaName;

    /**
     * 注解参数集合
     */
    private Set<AnnotateMeta> assignSet;

    public FieldMeta() {}

    public FieldMeta(VariableElement element, String metaName) {
        this.metaName = metaName;
        this.name = AptUtil.getElementName(element);
        this.label = getAssignLabel(element);
        this.assignSet = new HashSet<>();

    }

    public FieldMeta(VariableElement element, String metaName,
                     List<JCTree.JCAnnotation> annotations) {
        this(element, metaName);
        loadAssigns(annotations);
    }

    private String getAssignLabel(Element element) {
        // 从Element中获取DictMeta注解，并拿到label属性值
        String label = AptUtil.readJcAnnotationArg(element, metaName, "label");
        if (AptUtil.isEmpty(label)) {
            Objects.requireNonNull(this.name, "未指定字段名称: name");
            return this.name + "Label";
        }
        return label;
    }

    private void loadAssigns(List<JCTree.JCAnnotation> annotations) {
        if (null == annotations) {
            return;
        }

        for (JCTree.JCAnnotation annotation : annotations) {
            assignSet.add(new AnnotateMeta(annotation, name));
        }
    }

    public List<JCTree.JCAnnotation> newAnnotations(Function<AnnotateMeta, JCTree.JCAnnotation> function) {
        ListBuffer<JCTree.JCAnnotation> newAnnotations = new ListBuffer<>();
        for (AnnotateMeta value : assignSet) {
            JCTree.JCAnnotation jcAnnotation = function.apply(value);
            if (null != jcAnnotation) {
                newAnnotations.append(jcAnnotation);
            }
        }
        return newAnnotations.toList();
    }

    public String getName() {
        return name;
    }

    public String getLabel() {
        return label;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public void setMetaName(String metaName) {
        this.metaName = metaName;
    }

    public void setAssignSet(Set<AnnotateMeta> assignSet) {
        this.assignSet = assignSet;
    }

}